package stc.skymobi.netty.handler.codec.http.response;

import com.alibaba.fastjson.JSON;
import io.netty.channel.Channel;
import io.netty.handler.codec.http.HttpHeaders;
import io.netty.handler.codec.http.HttpRequest;
import io.netty.handler.codec.http.HttpResponse;
import io.netty.handler.codec.http.HttpResponseStatus;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import stc.skymobi.bean.tlv.encode.TLVEncoderOfBean;
import stc.skymobi.netty.util.NettyConstants;
import stc.skymobi.util.ByteUtils;
import stc.skymobi.util.Propertyable;

public class MixedSendbackResponseHelper implements SendbackResponseHelper {

    private static final Logger logger =
            LoggerFactory.getLogger(MixedSendbackResponseHelper.class);

    private NettyHttpResponseBuilder httpResponseBuilder;
    private NettyHttpResponseSender httpResponseSender;
    private TLVEncoderOfBean beanEncoder;

    public void makeAndSendback(Object responseBean, Propertyable requestBean) {
        if (logger.isDebugEnabled()) {
            logger.debug("sendback bean {} ", responseBean);
        }

        DefaultNettyResponseSource source = new DefaultNettyResponseSource();
        source.setStatus(HttpResponseStatus.OK);
        byte[] bytes;

        HttpRequest httpRequest = (HttpRequest) requestBean.getProperty(NettyConstants.HTTP_REQUEST);
        String contentType = httpRequest.headers().get(HttpHeaders.Names.CONTENT_TYPE);
        if (NettyConstants.TLV_TYPE.equalsIgnoreCase(contentType)) {
            source.setContentType(NettyConstants.TLV_TYPE);
            bytes = ByteUtils.union(
                    beanEncoder.encode(responseBean,
                            beanEncoder.getEncodeContextFactory().createEncodeContext(
                                    responseBean.getClass(), null)
                    )
            );
        } else if (NettyConstants.JSON_TYPE.equalsIgnoreCase(contentType)) {
            source.setContentType(NettyConstants.JSON_TYPE);
            bytes = JSON.toJSONBytes(responseBean);
        } else {
            throw new RuntimeException("UnKnown Content-Type " + contentType);
        }

        if (logger.isDebugEnabled()) {
            logger.debug("sendback bean as Hex \r\n{} ",
                    ByteUtils.bytesAsTLVHexString(bytes, 8096));
        }

        source.setContent(bytes);
        source.setContentLength(bytes.length);

        HttpResponse response = httpResponseBuilder.build(source);
        if (httpRequest != null) {
            String uuid = httpRequest.headers().get(NettyConstants.HEADER_UUID);
            if (uuid != null)
                response.headers().set(NettyConstants.HEADER_UUID, uuid);
            response.headers().set(HttpHeaders.Names.CONNECTION, httpRequest.headers().get(HttpHeaders.Names.CONNECTION));
        }
        httpResponseSender.sendResponse((Channel) requestBean.getProperty(NettyConstants.PROPERTY_CHANNEL), response);

    }

    public TLVEncoderOfBean getBeanEncoder() {
        return beanEncoder;
    }

    public void setBeanEncoder(TLVEncoderOfBean beanEncoder) {
        this.beanEncoder = beanEncoder;
    }

    public NettyHttpResponseBuilder getHttpResponseBuilder() {
        return httpResponseBuilder;
    }

    public void setHttpResponseBuilder(NettyHttpResponseBuilder httpResponseBuilder) {
        this.httpResponseBuilder = httpResponseBuilder;
    }

    public NettyHttpResponseSender getHttpResponseSender() {
        return httpResponseSender;
    }

    public void setHttpResponseSender(NettyHttpResponseSender httpResponseSender) {
        this.httpResponseSender = httpResponseSender;
    }
}
